#pragma once

#include <iostream>
#include <string>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define SIZE 1024

#define Info     0
#define Debug    1
#define Warning  2
#define Error    3
#define Fatal    4

#define Screen    1     //打印到屏幕
#define Onefile   2     //写到一个文件
#define Classfile 3     //写分类到不同文件

#define Logfile "log.txt"

using namespace std;

class Log
{
public:
    Log()
    {}
    Log(int printmethod,string path)
    :_printmethod(printmethod),_path(path)
    {}

    string Leveltostring(int level)
    {
        switch (level)
        {
        case Info:
            return "Info";
        case Debug:
            return "Dubug";
        case Warning:
            return "Warning";
        case Error:
            return "Error";
        case Fatal:
            return "Fatal";
        default:
            return "None";
        }
    }
    void operator()(int level,const char *format, ...)
    {
        //打印时间 snprintf的使用
        time_t t = time(nullptr);
        struct tm *nowtime = localtime(&t);
        char leftbuf[SIZE];
        snprintf(leftbuf, sizeof(leftbuf), "[%s][%d-%d-%d %d-%d-%d]", Leveltostring(level).c_str(),
                 nowtime->tm_year + 1900, nowtime->tm_mon + 1, nowtime->tm_mday, nowtime->tm_hour, nowtime->tm_min, nowtime->tm_sec);

        // 可变参数的处理  vsnprintf的使用
        va_list s;//va 这种都是宏，专门处理这些的
        va_start(s, format);
        char rightbuf[SIZE];
        vsnprintf(rightbuf, sizeof(rightbuf), format, s);
        va_end(s);
        //这样子就可以像printf一样有输出格式了

        string buf;
        buf += leftbuf;
        buf += rightbuf;
        Printlog(level, buf);
    }
    void Printlog(int level, const string& logtxt)
    {
        switch (_printmethod)
        {
        case Screen:
            cout << logtxt << endl;
            break;
        case Onefile:
            Printonefile(Logfile, logtxt);
            break;
        case Classfile:
            Printclassfile(level,logtxt);
            break;
        default:break;
        }
    }

    void Printonefile(string logfile, const string& logtxt)
    {
        int fd = open(logfile.c_str(), O_WRONLY|O_CREAT|O_APPEND,0664);
        if(fd<0)
        {
            perror("open");
            exit(1);
        }
        write(fd,logtxt.c_str(),logtxt.size());
        close(fd);
    }
    void Printclassfile(int level,const string& logtxt)
    {
        string filename=Logfile;
        filename+=".";
        filename+=Leveltostring(level);
        Printonefile(filename,logtxt);

    }
    ~Log()
    {}

private:
    int _printmethod = Screen;//默认打印在屏幕
    string _path = ".";//默认当前路径
};

Log log;
// Log log(Onefile,"./log.txt");//往一个文件写入，守护进程时可以这样做